package com.dbecom.platform.foundation.batch.job;

import java.util.Map;

import javax.sql.DataSource;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.JobParameter;
import org.springframework.batch.core.JobParameters;
import org.springframework.batch.core.Step;
import org.springframework.batch.core.StepContribution;
import org.springframework.batch.core.configuration.annotation.JobBuilderFactory;
import org.springframework.batch.core.configuration.annotation.StepBuilderFactory;
import org.springframework.batch.core.configuration.annotation.StepScope;
import org.springframework.batch.core.scope.context.ChunkContext;
import org.springframework.batch.core.step.tasklet.Tasklet;
import org.springframework.batch.item.ItemProcessor;
import org.springframework.batch.item.file.FlatFileItemReader;
import org.springframework.batch.item.file.LineMapper;
import org.springframework.batch.item.file.mapping.BeanWrapperFieldSetMapper;
import org.springframework.batch.item.file.mapping.DefaultLineMapper;
import org.springframework.batch.item.file.transform.DelimitedLineTokenizer;
import org.springframework.batch.repeat.RepeatStatus;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.core.JdbcTemplate;

import com.dbecom.platform.foundation.batch.Constants;
import com.dbecom.platform.foundation.batch.ECBatchException;
import com.dbecom.platform.foundation.batch.JobUtil;
import com.dbecom.platform.foundation.batch.config.BatchConfig;
import com.dbecom.platform.foundation.batch.listener.LogProcessListener;
import com.dbecom.platform.foundation.batch.model.CatalogGroupDTO;
import com.dbecom.platform.foundation.batch.processor.CatalogGroupJobProcessor;
import com.dbecom.platform.foundation.batch.writer.CatalogGroupWriter;

/**
 * @author lynn.xu
 *
 */
@Configuration
public class CatalogGroupJobConfig {

    protected final Log logger = LogFactory.getLog(this.getClass());

    @Autowired
    public BatchConfig batchConfig;

    @Autowired
    DataSource dataSource;

    @Autowired
    private JobBuilderFactory jobBuilders;

    @Autowired
    private StepBuilderFactory stepBuilders;

    @Bean
    public Job importCatalogGroupJob(Step step) {
        return jobBuilders.get("importCatalogGroupJob").listener(batchConfig.protocolListener()).start(step)
                .build();
    }

    @Bean
    public Step step(FlatFileItemReader<CatalogGroupDTO> reader) {
        return stepBuilders.get("step").<CatalogGroupDTO, CatalogGroupDTO> chunk(Constants.CATALOG_GROUP_CHUNK_SIZE)
                .reader(reader).processor(processor()).writer(writer()).listener(logProcessListener()).faultTolerant()
                .skip(ECBatchException.class).skipLimit(20).noRollback(ECBatchException.class)
                .noRetry(ECBatchException.class).build();
    }

//    .tasklet(this.tasklet())
//    @Bean
//    protected Tasklet tasklet() {
//        return new Tasklet() {
//            @Override
//            public RepeatStatus execute(StepContribution contribution, ChunkContext context) {
//
//                
//                JobParameters jobParameters = context.getStepContext().getStepExecution().getJobParameters();
//
//                if (jobParameters.isEmpty()) {
//                    log.info("{}", "No job parameters!");
//                } else {
//                    
//                    for (Map.Entry<String, JobParameter> param : jobParameters.getParameters().entrySet()) {
//                        
//                        if (param.getKey().contains("deleteDate")) {
//                            historyDate =  String.format("%s", param.getValue());
//                        }                       
//                    }
//                }
//        
//
//                jdbcTemplate = new JdbcTemplate(dataConfig.dataSource());
//
//                int rowCount = jdbcTemplate.update(SQL_DELETE_ACCESSORY, historyDate);
//
//                contribution.incrementWriteCount(totalCount);
//                return RepeatStatus.FINISHED;
//            }
//        };
//    }
        
    @Bean
    @StepScope
    public FlatFileItemReader<CatalogGroupDTO> reader(@Value("#{jobParameters[resourcePath]}") String resourcePath) {
        FlatFileItemReader<CatalogGroupDTO> itemReader = new FlatFileItemReader<CatalogGroupDTO>();
        itemReader.setLineMapper(lineMapper());
        itemReader.setResource(JobUtil.getResource(resourcePath));
        itemReader.setLinesToSkip(Constants.CATALOG_GROUP_HEADER_SKIP_NO);
        return itemReader;
    }

    @Bean
    public LineMapper<CatalogGroupDTO> lineMapper() {
        DefaultLineMapper<CatalogGroupDTO> lineMapper = new DefaultLineMapper<CatalogGroupDTO>();
        DelimitedLineTokenizer lineTokenizer = new DelimitedLineTokenizer();
        lineTokenizer.setNames(new String[] { "groupId", "topGroup", "parentGroupId", "sequence", "name",
                "shortDescription", "longDescription", "thumbnail", "FullImage", "Keyword", "delete"});
        BeanWrapperFieldSetMapper<CatalogGroupDTO> fieldSetMapper = new BeanWrapperFieldSetMapper<CatalogGroupDTO>();
        fieldSetMapper.setTargetType(CatalogGroupDTO.class);
        lineMapper.setLineTokenizer(lineTokenizer);
        lineMapper.setFieldSetMapper(fieldSetMapper);
        return lineMapper;
    }

    @Bean
    public ItemProcessor<? super CatalogGroupDTO, ? extends CatalogGroupDTO> processor() {
        return new CatalogGroupJobProcessor();
    }

    @Bean
    public CatalogGroupWriter writer() {
        return new CatalogGroupWriter();
    }

    @Bean
    public JdbcTemplate jdbcTemplate() {
        return new JdbcTemplate(dataSource);
    }
    
    @Bean
    public LogProcessListener logProcessListener(){
        return new LogProcessListener();
    }

}
